#!/usr/bin/perl
use FindBin;
use lib $FindBin::Bin;
use lib "$FindBin::Bin/lib";
use lib "$FindBin::Bin/../lib";
use lib "$FindBin::Bin/../plib/lib/perl5";

use strict;

use JSON;
use Getopt::Long;
use AutoExecUtils;
use CollectObjCat;
use StorageBase;

sub usage {
    my $pname = $FindBin::Script;
    print("INFO: :option --node or --type not defined.\n");
    print("$pname --node <node> --type <type> .\n");
    exit(0);
}

sub main {
    $| = 1;    #不对输出进行buffer，便于实时看到输出日志
    AutoExecUtils::setEnv();

    my ( $node, $type );

    my $isVerbose = 0;
    my $defaultCommunity;
    my $timeout = 10;
    my $inspect = 0;

    GetOptions(
        'verbose=i'   => \$isVerbose,
        'node=s'      => \$node,
        'type=s'      => \$type,
        'inspect=i'   => \$inspect,
        'community=s' => \$defaultCommunity,
        'timeout=i'   => \$timeout
    );

    my $nodeInfo  = {};
    my $hasOptErr = 0;
    if ( not defined($node) ) {
        $node = $ENV{AUTOEXEC_NODE};
    }

    if ( not defined($node) or $node eq '' ) {
        $hasOptErr = 1;
    }
    else {
        $nodeInfo = from_json($node);
    }

    if ( $hasOptErr == 1 ) {
        usage();
    }

    if ( not defined($timeout) ) {
        $timeout = 10;
    }

    my $hostname  = $nodeInfo->{host};
    my $community = $nodeInfo->{password};
    if ( not defined($community) or $community eq '' ) {
        $community = $defaultCommunity;
    }
    if ( not defined($community) or $community eq '' ) {
        $community = 'public';
    }

    my $isFailed = 0;

    my $brand       = $type;
    my $storageBase = StorageBase->new( hostname => $hostname, community => $community, timeout => $timeout, node => $nodeInfo, inspect => $inspect );
    if ( not defined($type) or $type eq '' or $type eq 'auto' ) {
        $brand = $storageBase->getBrand();
    }

    if ( not defined($brand) or $brand eq '' ) {
        $isFailed = 1;
        print("ERROR: Can not discover the storage device brand.\n");
    }
    else {
        print("INFO: Storage brand: $brand.\n");
    }

    if ( $brand eq 'EMC_Vplex' ) {
        exec(qq{$FindBin::Bin/vplexunitycollector --node '$node' --inspect $inspect --timeout $timeout --verbose $isVerbose});
    }
    elsif ( $brand eq 'HP_3PAR' ) {
        exec(qq{$FindBin::Bin/hp3parcollector --node '$node' --inspect $inspect --timeout $timeout --verbose $isVerbose});
    }

    my $storageIns;
    my $storageClass = "Storage$brand";
    if ( -e "$FindBin::Bin/$storageClass.pm" or -e "$FindBin::Bin/lib/$storageClass.pm" ) {
        print("INFO: Has defined class $storageClass, try to load it.\n");
        eval {
            require "$storageClass.pm";
            $storageIns = $storageClass->new( hostname => $hostname, community => $community, timeout => $timeout, node => $nodeInfo, inspect => $inspect );
        };
        if ($@) {
            $isFailed = 1;
            print("WARN: Load $storageClass failed, $@");
            print("WARN: Fall back to StorageBase class.\n");
            $storageIns = $storageBase;
        }
        else {
            print("INFO: Class $storageClass loaded.\n");
        }
    }
    else {
        $isFailed = 1;
        print("INFO: $storageClass not found.\n");
        print("INFO: Fall back to StorageBase class.\n");
        $storageIns = $storageBase;
    }

    my $data = $storageIns->collect();

    my $objCat = CollectObjCat->get('STORAGE');
    $data->{_OBJ_CATEGORY} = $objCat;
    if ( not defined( $data->{_OBJ_TYPE} ) ) {
        $data->{_OBJ_TYPE} = 'Storage';
    }
    if ( not defined( $data->{_APP_TYPE} ) ) {
        $data->{_APP_TYPE} = $brand;
    }

    $data->{MGMT_IP}     = $nodeInfo->{host};
    $data->{PK}          = CollectObjCat->getPK($objCat);
    $data->{RESOURCE_ID} = $nodeInfo->{resourceId};

    my $out = {};
    $out->{DATA} = [$data];
    AutoExecUtils::saveOutput($out);
    if ( $isVerbose == 1 ) {
        print("==================\n");
        print( to_json( $data, { pretty => 1 } ) );
        print("==================\n");
    }

    return $isFailed;
}

exit main();
